<?php

/**
 * \file
 * Classe principale des blocs.
 */

/**
 * Définition, gestion et affichage de blocs.
 */ 
namespace pilar\Blocks /* \cond */ ; /* \endcond */
{

/**
 * TODO
 * Créer plusieurs types de blocs en fonction du niveau de cache
 * nécessaire. En regroupant toutes les fonctionnalités communes dans une
 * classe abstraite parente.
 */

/**
 * Classe permettant l'affichage de blocs de contenus.
 *
 * Toute classe qui définit un bloc doit hériter de cette classe.
 * 
 * Un cache est géré en interne.
 *
 * \todo
 * Faire de distingo entre identifiant de classe et identifiant de bloc.
 * Actuellement les identifiants de blocs ont tendance à être trop longs.
 *
 * \todo
 * Rendre indépendant de $TRACE qui fait partie de Toguna.
 *
 * \since 16/06/2008
 * \author Matthieu OVIEDO <matthieu.oviedo@gmail.com>
 */
abstract class Block extends \object {

/**
 * Identifiant complet du bloc.
 *
 * \since 28/10/2008
 */
private $_id = null;


/**
 * Durée de vie du cache en secondes. Nulle si le cache est désactivé
 * (par défaut).
 *
 * \todo
 * Renommer en $_cacheTime et rendre privé.
 */
public $cacheTime;


/**
 * Tableau des paramètres d'entrée du contenu.
 * 
 * Ils sont aussi utilisés par le cache pour identifier chaque instance
 * du bloc mise en cache.
 *
 * \todo
 * Renommer en $_contentParams 
 */
public $contentParams;


/**
 * Zones de diffusion du bloc.
 * \since 10/09/2008
 */
private $_areas = array();


/**
 * Spécifie que la fonction `load` du bloc a été appelée.
 * \since 22/09/2008.
 */
private $_loaded = false;


/**
 * Chemin d'accès du contenu du bloc.
 *
 * \since 29/09/2008
 */
private $_contentPath = null;


/**
 * Chemins d'accès des fichiers dont dépend le contenu du bloc.
 *
 * \since 10/12/2008
 */
private $_contentPrecedingFiles = array();


/**
 * Styles à appliquer au contenu de bloc.
 *
 * \since 13/10/2008
 */
private $_styles = array();


/**
 * Classes CSS associées au bloc.
 *
 * Par défaut on associe à tous les blocs la classe 'block'.
 *
 * \since 14/10/2008
 */
private $_cssClasses = array('block');


/**
 * Chemin d'accès de la présentation du bloc.
 *
 * \since 29/09/2008
 */
private $_presentationPath = null;


/**
 * Redirections associés au bloc. L'identifiant se fait par nom.
 *
 * \since 16/04/2009
 */
private $_redirections = array();


protected function loadDefaultParams() {
 parent::loadDefaultParams();

 $this->params->define(array(
  'defaultCacheTime' => 600, // Durée de cache par défaut, en secondes.
  'cssBlockClasses' => array(), // Classes CSS associée à l'élément racine
                                // du bloc.
  'styles' => array(),   // Feuilles de style XSL à appliquer au bloc.
  'style' => '', // Style à utiliser pour la feuille de style par défaut.
  'localId' => '', // Identifiant local.
 ));
}


protected function initialize() {
 parent::initialize();
 global $TRACE;

 $this->contentParams = array();
 $this->cacheTime = $this->get('defaultCacheTime');

 // Ajout des styles passés en paramètre aux styles du bloc, et du style par
 // défaut en cas d'absence :
  if(count($this->get('styles')) != 0) {
   foreach($this->get('styles') as $stylePath) {
    if(!($this->addStyleIfExists(KER_CURRENT_THEME_PATH.$stylePath)))
    {
     $this->addStyleIfExists(KER_THEMES_PATH.'/simple'.$stylePath);
    }
   }
  } else {
   $this->loadDefaultStyle();
  }
  
 // Ajout des classes CSS passées en paramètre aux classes CSS du bloc :
  foreach($this->get('cssBlockClasses') as $cssClassName) {
   $this->addCssClass($cssClassName);
  }
}


/**
 * Génère l'identifiant d'un élément associé au bloc.
 *
 * Cet identifiant est compatible avec XHTML, CSS, Javascript et variables
 * GET et POST de PHP.
 *
 * \param $n Identifiant local de l'élément.
 * \return Identifiant global de l'élément.
 *
 * \since 28/10/2008
 **/
public function globalId($n) {
 return $this->id().'_'.$n;
}


/**
 * Accède à l'identifiant du bloc.
 *
 * \return Identifiant du bloc.
 *
 * \since 07/03/2009
 */
public function id() {
 if ($this->_id == null) {
  // Construction de l'identifiant complet du bloc :
   $this->_id = str_replace(
    '\\', '_',
    get_class($this).$this->get('localId')
   );
 }

 return $this->_id;
}


/**
 * Accède au contenu d'une variable POST associée.
 *
 * \param $n Identifiant local de la variable.
 * \return Contenu de la variable POST si elle existe, NULL sinon.
 *
 * \see globalId
 * \see getVarValue
 *
 * \since 28/10/2008 
 **/
public function postVarValue($n) {
 $i = $this->globalId($n);
 if(isset($_POST[$i])) return $_POST[$i];
 else return null;
}


/**
 * Accède au contenu d'une variable GET associée.
 *
 * \param $n Identifiant local de la variable.
 * \return Contenu de la variable GET si elle existe, NULL sinon.
 *
 * \see globalId
 * \see postVarValue
 *
 * \since 28/10/2008 
 **/
public function getVarValue($n) {
 $i = $this->globalId($n);
 if(isset($_GET[$i])) return $_GET[$i];
 else return null;
}


/**
 * Acc�s àune redirection donn�e.
 *
 * \param $name Nom de la redirection en question.
 * \return Redirection en question.
 * \since 16/04/2009 
 */
public function redirection($name) {
 if (isset($this->_redirections[$name])) {
  return $this->_redirections[$name];
 }
}


/**
 *
 */
public function addRedirection($redirection) {
 $this->_redirections[$redirection->get('name')] = $redirection;
}

/**
 * Déclenche le `chargement` du bloc.
 * \since 22/09/2008
 */
public function doLoad() {
 if (!$this->_loaded) {
  if ($this->authorized()) {
   $this->load();
   $this->_loaded = true;
  }
 }
}


/**
 * Est sensée `charger` le bloc. C'est à dire l'initialiser en prenant à la
 * fois en compte les paramètres de construction et les paramètres de 
 * contenu.*
 * \since 22/09/2008
 */
protected function load() { }


/**
 * Définit la durée de vie maximale du cache. Elle est exprimée en
 * secondes et nulle si le cache est désactivé.
 * 
 * En général cette fonction est utilisée dans le constructeur d'un
 * bloc pour lui associer une durée par défaut, mais elle peut
 * également être utilisée spécifiquement avant affichage du bloc si
 * on souhaite désactiver le cache ou choisir manuellement sa durée de
 * vie.
 * 
 * \since 16/06/2008
 * \param $cacheTime Durée de vie du cache en secondes.
 */
public function setCacheTime($cacheTime) {
 $this->cacheTime = $cacheTime;
}


/**
 * Activité du cache.
 *
 * \since 29/09/2008
 * \return Activité du cache (TRUE/FALSE).
 */
private function cacheIsEnabled() {
 return (KER_BLOCKS_CACHE_ACTIVE && $this->cacheTime != 0);
}


/**
 * Charge un style par défaut. Ajoute le style par défaut du bloc à partir du
 * thème courant utilisé sur Toguna et ajoute une classe associée à ce style
 * à l'élément HTML racine du bloc.
 *
 * \todo
 * Optimiser en fusionnant les deux boucles ?
 *
 * \todo
 * Retirer le code obsolète dans le "if".
 *
 * \since 13/10/2008
 */
private function loadDefaultStyle() {
 // On établie la liste des candidats potentiels par ordre de priorité :
  $candidates = array();
  $class = get_class($this);
  $i = 0;
  while($class != 'pilar\\Blocks\\Block') {
   if($this->get('style') != '') {
    $candidates[] = $class.'__'.$this->get('style');
   }
   $candidates[] = $class;
   $class = get_parent_class($class); // Récursion.
  }

 // Recherche du meilleur candidat existant :
  foreach($candidates as $class) {
   // Calcul du chemin du style relativement au thème :
    $path = '/'.str_replace('\\', '/', $class).'.xsl';

   // Calcul du chemin d'accès absolu :
    $fullPath = KER_CURRENT_THEME_PATH.$path;
    $fullDefaultPath = KER_THEMES_PATH.'/simple'.$path;
  
   // On essaie d'ajouter le style et en cas de succès on ajoute la classe CSS
   // correspondante et on sort :
    if($this->addStyleIfExists($fullPath)) {
     $this->addCssClass(
      str_replace('\\', '_', $class)
     );
     return;
    }else if($this->addStyleIfExists($fullDefaultPath)) {
     $this->addCssClass(
      str_replace('\\', '_', $class)
     );
     return;
    }
  }
}


/**
 * Ajoute un style au bloc si celui-ci existe.
 *
 * \since 13/10/2008
 * \param $stylePath Chemin d'accès absolu vers le fichier (potentiel) du
 *                   style.
 * \return \c TRUE si le style existe, \c FALSE sinon.
 */
private function addStyleIfExists($stylePath) {
 if(file_exists($stylePath)) {
  $this->addStyle($stylePath);
  return true;
 } else return false;
}


/**
 * Ajoute un styles aux styles du bloc.
 *
 * \since 13/10/2008
 * \param $stylePath Chemin d'accès absolu vers le fichier de style.
 */
public function addStyle($stylePath) {
 $this->_styles[] = $stylePath;
}


/**
 * Présence de styles.
 * 
 * \since 29/09/2008
 * \return Présence de styles (TRUE/FALSE).
 */
private function hasStyles() {
 return count($this->_styles) != 0;
}


/**
 * Ajoute une classe CSS au bloc.
 *
 * \since 14/10/2008
 * \param $cssClassName Nom de la classe CSS à ajouter.
 */
public function addCssClass($cssClassName) {
 $this->_cssClasses[] = $cssClassName;
}


/**
 * Permet de changer la valeur d'un paramètre de contenu.
 *
 * \todo Remplacer les paramètre de contenu par une gestion plus objet ?
 *
 * \since 16/06/2008
 * \param $name Nom du paramètre dont on veut modifier la valeur.
 * \param $value Nouvelle valeur du paramètre.
 * \see $contentParams
 */
public function setContentParam($name, $value) {
 $this->contentParams[$name] = $value;
}


/**
 * Valeur d'un paramètre de contenu.
 *
 * \todo Vérifier l'existence du paramètre ?
 *
 * \param $name Nom du paramètre.
 * \return Valeur du paramètre.
 *
 * \since 07/12/2008
 */
public function contentParam($name) {
 return $this->contentParams[$name];
}


/**
 * Retourne l'identifiant associé aux paramètres de contenu.
 * 
 * Les paramètres sont pris dans leur ordre de déclaration.
 * 
 * Exemples de valeurs retournées :
 *  - "?id:12?mode:adv?"
 *  - "??"
 *
 * Cette syntaxe permet d'effectuer une suppression sélective (en
 * fonction des paramètres de contenu) sur l'ensemble des instances
 * du bloc.
 *
 * \since 16/06/2008
 * \return La chaine associée aux paramètres de contenu.
 * \see $contentParams
 */
private function contentParamsId() {
 $inner = array();
 foreach ($this->contentParams as $name => $value) {
  // La fonction "urlencode" est utilisée pour échapper les données
  // sensibles :
   $inner[] = urlencode((binary)$name).'='.urlencode((binary)$value);
 }
 return '?'.implode('??', $inner).'?';
}


/**
 * Génère l'identifiant associé aux styles du bloc.
 *
 * \since 29/09/2008
 * \return Identifiant des styles du bloc.
 */
private function stylesId() {
 /* NOTE
  * Se renseigner sur les probabilités de collisions suscitées par la méthode
  * ci-dessous.
  */
 $str = '';
 foreach($this->_styles as $stylePath) {
  $str .= $stylePath.'|';
 }
 return md5($str);
}


/**
 * Crée un fichier temporaire et retourne son chemin d'accès.
 * 
 * \since 29/09/2008
 * \return Chemin d'accès vers le nouveau fichier.
 */
private function tempPath() {
 return tempnam(
  KER_BLOCKS_TEMP_PATH,
  '_'
 );
}


/**
 * Chemin d'accès du dossier de cache du bloc.
 *
 * \since 29/09/2008
 * \return Le chemin d'accès.
 */
private function cacheDirectoryPath() {
 /* TODO
  * Voir la nécessité d'un cache.
  */
 return KER_BLOCKS_CACHE_PATH.'/'.str_replace('\\', '/', get_class($this));
}


/**
 * Construit le chemin d'accès du contenu du bloc.
 *
 * \return Le chemin d'accès du contenu.
 *
 * \since 29/09/2008
 */
private function makeContentPath() {
 if($this->cacheIsEnabled()) { // Cache actif.
  return $this->cacheDirectoryPath().'/'.$this->contentParamsId();
 } else { // Cache inactif.
  return $this->tempPath();
 }
}


/**
 * Chemin d'accès du contenu du bloc.
 *
 * \return Le chemin d'accès du contenu.
 *
 * \since 29/09/2008
 */
private function contentPath() {
 if($this->_contentPath == null) {
  $this->_contentPath = $this->makeContentPath();
 }
 
 return $this->_contentPath;
}


/**
 * Construit le chemin d'accès de la présentation du bloc.
 *
 * \return Le chemin d'accès de la présentation du bloc.
 *
 * \since 29/09/2008
 */
private function makePresentationPath() {
 if($this->cacheIsEnabled()) { // Cache actif.
  return $this->contentPath().'~'.$this->stylesId();
 } else { // Cache inactif.
  return $this->tempPath();
 }
}


/**
 * Chemin d'accès de la présentation du bloc.
 *
 * \return Chemin d'accès de la présentation.
 *
 * \since 29/09/2008
 */
private function presentationPath() {
 if($this->_presentationPath == null) {
  $this->_presentationPath = $this->makePresentationPath();
 }
 
 return $this->_presentationPath;
}


/**
 * Ecrit des données dans un fichier en s'assurant de l'existence des
 * dossiers parents.
 *
 * \todo Voir d'activer la vérification des dossiers parents uniquement en
 * mode développement ?
 *
 * \since 29/09/2008
 */
private function writeFile($path, $content) {
 // On s'assure que tous les dossiers parents existent :
  $dir = dirname($path);
  if(!file_exists($dir)) {
   mkdir($dir, 0777, true);
  }
  
 // Ecriture du fichier :
  $fp = fopen($path, 'a');
  flock($fp, LOCK_EX);
  ftruncate($fp, 0);
  fwrite($fp, $content);
  fclose($fp);
  
 // Changement des accès du fichier :
  chmod($path, 0755);
}


/**
 * Ajoute une ou plusieurs zones de diffusion quelconques au bloc en écrasant
 * les zones existantes avec les mêmes noms.
 * \since 10/09/2008
 * \param $ Liste de zones de diffusion à ajouter.
 */
public function addAreas() {
 foreach(func_get_args() as $area) {
  $area->parentBlock = $this;
  $this->_areas[$area->get('name')] = $area;
 }
}


/**
 * Instancie et ajoute une zone de diffusion deubaze au bloc.
 *
 * Si une zone avec un même nom existe déjà alors elle est écrasée.
 *
 * \since 28/10/2008
 * \param $name Nom de la zone de diffusion à créer et ajouter.
 * \return Instance de la nouvelle zone de diffusion.
 */
public function newArea($name) {
 $area = new Area(array('name' => $name));
 $area->parentBlock = $this;
 $this->_areas[$name] = $area;
 return $area;
}


/**
 * Instancie et ajoute une ou plusieurs zones de diffusion deubaze au bloc en
 * écrasant les zones existantes avec les mêmes noms.
 * \since 10/09/2008
 * \param $ Liste des noms des zones à créer.
 */
public function newAreas() {
 foreach(func_get_args() as $name) {
  $this->newArea($name);
 }
}


/**
 * Accède à une zone de diffusion par son nom.
 * \since 10/09/2008
 * \param $name Nom de la zone.
 * \return Zone de diffusion en question.
 */
public function area($name) {
 /**
  * TODO
  * Emettre un message d'erreur si la zone n'existe pas.
  */
 return $this->_areas[$name];
}


/**
 * Génère le noeud DOM racine du contenu du bloc.
 *
 * \param $domDoc \c DOMDocument hôte du contenu.
 * \return DOMNode racine du contenu.
 *
 * \see buildContent
 *
 * \since 16/06/2008
 */
abstract protected function buildContentRoot($domDoc);


/**
 * Détermine si le contenu est dépassé.
 *
 * \return \c TRUE si le fichier de contenu est dépassé, \c FALSE sinon.
 * 
 * \since 29/09/2008
 */
private function contentIsOutdated() {
 // Fonction cache inactive ?
  if(!$this->cacheIsEnabled()) return true;

 $contentPath = $this->contentPath();

 // Fichier de cache inexistant ?
  if(!file_exists($contentPath)) return true;
 
 // Récupération de la date de modification du fichier de contenu :
  $contentDate = filemtime($contentPath);
 
 // Expiration du fichier de cache ?
  if(time() - $contentDate >= $this->cacheTime) return true;
 
 // Fichier de précédance mis à jour ?
  foreach($this->_contentPrecedingFiles as $path) {
   if(file_exists($path) && filemtime($path) > $contentDate) return true;
  }
 
 return false; // Le fichier de contenu est d'actualité !
}


/**
 * Construction du contenu du bloc et enregistrement.
 *
 * \return \c DOMDocument du contenu.
 * 
 * \since 29/09/2008
 */
private function buildContent() {
 // Nouveau document DOM pour le contenu :
  $domContent = new \DOMDocument();

 // Récupération du noeud DOM racine du contenu et ajout au document DOM :
  $domRoot = $this->buildContentRoot($domContent);
  $domContent->appendChild($domRoot);

 // Enregistrement sur disque :
  $this->writeFile(
   $this->contentPath(),
   $domContent->saveXML()
  );

 return $domContent;
}


/**
 * Charge le contenu du bloc à partir du fichier en cache.
 *
 * \return \c DOMDocument du contenu.
 *
 * \since 11/12/2008
 */
private function loadContent() {
 $domContent = new \DOMDocument();
 $domContent->load($this->contentPath());
 return $domContent;
}


/**
 * Détermine si le fichier de présentation en cache est dépassé.
 *
 * La vérification est faite indépendamment du contenu. Elle prend en
 * compte uniquement les fichiers de styles.
 *
 * \todo Voir de n'activer cette fonction qu'en cas de développement
 * ou de design.
 *
 * \return \c TRUE si le fichier de présentation est périmé, \c FALSE sinon. 
 *
 * \since 29/09/2008
 */
private function presentationIsOutdated() {
 // Récupération du chemin d'accès du fichier de présentation :
  $path = $this->presentationPath();

 if(!$this->cacheIsEnabled() || // Fonction cache inactive.
    !file_exists($path) // Fichier de cache inexistant.
 ) return true;
 
 // A ce stade on regarde si le fichier de cache est périmé relativement
 // à ses styles.
 
 // Récupération de la date de la dernière modification du fichier de
 // présentation :
  $mtime = filemtime($path);

 // Péremption de la présentation par rapport aux styles :
  foreach($this->get('styles') as $stylePath) {
   if(filemtime($stylePath) > $mtime) return true;
  }

 return false; // Le fichier de présentation est d'actualité !
}


/**
 * Produit la présentation à partir du contenu et l'enregistre.
 *
 * La fonction applique les différents styles au contenu.
 *
 * \todo Éventuellement voir si un même bloc peut être affiché plusieurs
 * fois et à ce moment là prévoir l'enregistrement en instance du
 * processeur XSLT afin d'éviter de l'initialiser plusieurs fois
 * inutilement.
 *
 * \param $domContent \c DOMDocument du contenu.
 * 
 * \since 29/09/2008
 */
private function buildPresentation(\DOMDocument $domContent) {
 // Initialisation du processeur XSLT :
  $proc = new \XSLTProcessor;
  
 // Chargement des styles dans le processeur XSLT :
  foreach($this->_styles as $stylePath) {
   // Chargement du style considéré :
    $xsl = new \DOMDocument;
    $xsl->load($stylePath);
   // Ajout du style au processeur XSLT :
    $proc->importStyleSheet($xsl);
  }
   
 // Exécution des transformations et enregistrement sur disque :
  $this->writeFile(
   $this->presentationPath(),
   $proc->transformToXML($domContent)
  );
}


/**
 * Supprime les fichiers temporaires mis en jeux dans le processus de
 * génération du bloc.
 *
 * \toto
 * Comprendre pourquoi le "1==0".
 *
 * \since 29/09/2008
 */
private function clean() {
 if(!$this->cacheIsEnabled() && 1==0) { // Fonction cache inactive.
  unlink($this->contentPath());
  if($this->hasStyles()) unlink($this->presentationPath());
 }
}


/**
 * Affiche le résultat final du bloc sur la sortie standard.
 * 
 * \todo
 * Trouver un module de coloration syntaxique pour le XML.
 *
 * \since 16/06/2008
 */
final public function display() {
 if (!$this->authorized()) return;

 // Initialisation de l'activité du bloc sur la trace :
  $traceBlock = new \debug\block(
   get_class($this)
  );
  $traceBlock->begin();
  $traceBlock->params = $this->contentParamsId();

 // On force le chargement du bloc si ce n'est déjà fait :
  $this->doLoad();

 // Mise à jour du contenu ou de la présentation si nécessaire :
  if ($this->hasStyles()) {
   if ($this->contentIsOutdated()) {
    $this->buildPresentation($this->buildContent());
   } else {
    if ($this->presentationIsOutdated()) {
     $this->buildPresentation($this->loadContent());
    }
   }
  } elseif ($this->contentIsOutdated()) {
   $this->buildContent();
  }
 
 // Calcul de la source du bloc pour l'affichage :
  $srcCode = nl2br(
              str_replace(' ', '&nbsp;',
               htmlentities(
                `xmllint --format {$this->contentPath()}`,
                ENT_COMPAT,
                'UTF-8'
               )
              )
             );
  
 // Affichage du résultat final sur la sortie standard par inclusion PHP dans
 // une balise XHTML DIV conteneur.
?>

<div id="<?php echo $this->id() ?>"<?php if(!empty($this->_cssClasses)) { ?> class="<?php echo implode(' ', $this->_cssClasses) ?>"<?php } ?>>
<?php $this->specialHtmlHeader() ?>
<?php if($this->hasStyles()) { include($this->presentationPath()); } ?>
<?php $this->specialHtmlFooter() ?>
<?php if(KER_BLOCKS_DETAILS_SHOW) { ?>
<?php  $tmpId = md5(microtime()); ?>
<div class="blockInfo" id="<?php echo $tmpId ?>-block">#</div>
<script type="text/javascript">
 $(document).ready(function() {
  $('#<?php echo $tmpId ?>-block').click(function() {
   $('#<?php echo $tmpId ?>').toggle('slow');
  });
 });
</script>
<div class="blockSrc" id="<?php echo $tmpId ?>">
 <div class="stereotype">&lt;<?php echo get_class($this) ?>&gt;</div>
 <div class="contentFile"><?php echo $this->contentPath() ?></div>
 <div class="styles">
<?php foreach($this->_styles as $style) { ?>
 <?php echo \html($style) ?><br /> 
<?php } ?>
 </div>
 <div class="presentationFile"><?php echo $this->presentationPath() ?></div>
 <code><?php echo $srcCode ?></code>
</div>
<?php } ?>
</div>
<?php

 // On effectue le ménage des fichiers temporaires (il n'y en a pas toujours) :
  $this->clean();

 // Clôture de l'activité du bloc sur la trace :
  $traceBlock->setCacheStatus(false);
  $traceBlock->end();
}


/**
 * Affiche sur la sortie standard un code HTML spécial à placer avant le
 * contenu stylisé dans le résultat final.
 * Utilisé par exemple pour les formulaires.
 *
 * \since 14/10/2008
 */
protected function specialHtmlHeader() { }


/**
 * Affiche sur la sortie standard un code HTML spécial à placer après le
 * contenu stylisé dans le résultat final.
 * Utilisé par exemple pour les formulaires.
 *
 * \since 14/10/2008
 */
protected function specialHtmlFooter() { }


/**
 * Actions associées au bloc à exécuter dans le header de la page.*
 * 
 * \since 13/09/2008
 */
protected function actions() { }


/**
 * S'occupe d'exécuter les actions du bloc.
 * \since 13/09/2008
 */
public function doActions() {
 $this->doLoad();

 $this->actions();
 foreach($this->_areas as $name => $area) {
  $area->doActions();
 }
}


/**
 * Ajoute un fichier de précédance au contenu.
 *
 * \param $path Chemin d'accès du fichier.
 *
 * \since 10/12/2008
 */
public function addContentPrecedingFile($path) {
 $this->_contentPrecedingFiles[] = $path;
}


/**
 * Détermine si le bloc peut être oui ou non affiché.
 *
 * Par défaut cette fonction retourne \c TRUE, mais elle peut être
 * surchargée afin de gérer les droits d'accès sur le bloc.
 *
 * \warning
 * Cette fonction ne doit jamais être appelée directement pour vérifier
 * le statut d'autorisation d'un bloc. Pour cela utiliser la fonction \a
 * authorized().
 *
 * \return \c TRUE si le bloc peut être affiché, \c FALSE sinon.
 *
 * \see authorized()
 *
 * \since 01/06/2009
 * \author Matthieu OVIEDO <matthieu.oviedo@gmail.com>
 */
protected function buildAuthorization() {
 return true; // Comportement par défaut (aucune protection).
}


/**
 * Permet de savoir si le bloc est autorisé à être affiché dans le
 * contexte courant.
 *
 * Le contexte peut par exemple concerner l'utilisateur courant, la date
 * courante, etc.
 *
 * \todo
 * Eventuellement mettre en place un cache local afin d'éviter
 * l'évaluation multiple du statut.
 *
 * \return \c TRUE si le bloc est affichable, \c FALSE sinon.
 *
 * \since 01/06/2009
 * \author Matthieu OVIEDO <matthieu.oviedo@gmail.com>
 */
final public function authorized() {
 return $this->buildAuthorization();
}


public function getRedirections() {
	return $this->_redirections;
}

} // Class.

} // Namespace.

?>
